/**
 * Computes the 128-bit CityHash of a string.  Only designed & tested for seed generation,
 * may be suboptimal as a general 128-bit hash.
 * Source: https://stackoverflow.com/questions/521295/seeding-the-random-number-generator-in-javascript
 * @param str String to hash
 * @returns 4 32-bit unsigned integers comprising the 128-bit hash
 */
export function cyrb128(str: string) {
  let h1 = 1779033703;
  let h2 = 3144134277;
  let h3 = 1013904242;
  let h4 = 2773480762;
  for (let i = 0, k; i < str.length; i++) {
    k = str.charCodeAt(i);
    h1 = h2 ^ Math.imul(h1 ^ k, 597399067);
    h2 = h3 ^ Math.imul(h2 ^ k, 2869860233);
    h3 = h4 ^ Math.imul(h3 ^ k, 951274213);
    h4 = h1 ^ Math.imul(h4 ^ k, 2716044179);
  }
  h1 = Math.imul(h3 ^ (h1 >>> 18), 597399067);
  h2 = Math.imul(h4 ^ (h2 >>> 22), 2869860233);
  h3 = Math.imul(h1 ^ (h3 >>> 17), 951274213);
  h4 = Math.imul(h2 ^ (h4 >>> 19), 2716044179);
  h1 ^= h2 ^ h3 ^ h4;
  h2 ^= h1;
  h3 ^= h1;
  h4 ^= h1;
  return [h1 >>> 0, h2 >>> 0, h3 >>> 0, h4 >>> 0];
}

/**
 * SplitMix32 PRNG
 * Source: https://stackoverflow.com/questions/521295/seeding-the-random-number-generator-in-javascript
 * @param a Seed value
 * @returns Pseudorandom number generator function that returns a float in [0, 1)
 */
export function splitmix32(a: number) {
  return function () {
    a |= 0;
    a = (a + 0x9e3779b9) | 0;
    let t = a ^ (a >>> 16);
    t = Math.imul(t, 0x21f0aaad);
    t ^= t >>> 15;
    t = Math.imul(t, 0x735a2d97);
    return ((t ^= t >>> 15) >>> 0) / 4294967296;
  };
}
